package com.ruoyi.common.utils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ruoyi.common.Constant;
import com.ruoyi.common.Result;
import com.ruoyi.common.Utils;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.pojo.AccessToken;
import com.ruoyi.common.pojo.WxPhoneInfo;
import com.ruoyi.common.pojo.WxSignature;
import com.ruoyi.common.pojo.WxTicket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Modifier;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

@Component
public class WxUtils {
    @Autowired
    private RuoYiConfig humanResourcesProperty;
    private static final Logger logger = LoggerFactory.getLogger(WxUtils.class);

    private static GsonBuilder gsonBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss");
    private final static Gson gson = gsonBuilder.disableHtmlEscaping()
            .excludeFieldsWithModifiers(Modifier.PROTECTED, Modifier.TRANSIENT, Modifier.STATIC).create();
    private final static String DEFAULT_USER_FAIL = "获取用户信息失败";
    private final static String DEFAULT_SIGN_FAIL = "获取用户签名失败";

    /**
     * @param wxCode = null 客户端模式
     *               有值 微信授权码模式
     **/
    public Result getAccessToken(String wxCode) {
        RuoYiConfig.WeChat weChat = humanResourcesProperty.getWechat();
        String url = null;
        if (StringUtils.isEmpty(wxCode)) {
            //客户端模式
            url = String.format(weChat.getClientAccessTokenUrl(), weChat.getAppId(), weChat.getAppScret());
        } else {
            //微信授权码模式
            url = String.format(weChat.getAccessTokenUrl(), weChat.getAppId(), weChat.getAppScret(), wxCode);
        }

        Result acctokenResult = WebUtil.doGet(url);
        if (acctokenResult.getCode() == Constant.FAIL_) {
            return Result.FAIL(DEFAULT_USER_FAIL);
        }
        AccessToken accessToken = gson.fromJson(acctokenResult.getData().toString(), AccessToken.class);

        return Result.SUCCESS(accessToken);
    }

    public Result getSignature(String url) {
        logger.info("getSignature :接收参数{}", url);
        RuoYiConfig.WeChat weChat = humanResourcesProperty.getWechat();
        Result accessTokenResult = getAccessToken(null);
        logger.info("获取accessToken :{}", gson.toJson(accessTokenResult));
        if (accessTokenResult.getCode() == Constant.FAIL_) {
            return Result.FAIL(DEFAULT_SIGN_FAIL);
        }
        AccessToken accessToken = (AccessToken) accessTokenResult.getData();
        Result ticketResult = getTicket(accessToken.getAccess_token());
        logger.info("获取ticket: {}", gson.toJson(ticketResult));
        if (ticketResult.getCode() == Constant.FAIL_)
            return Result.FAIL(DEFAULT_SIGN_FAIL);
        WxTicket wxTicket = (WxTicket) ticketResult.getData();
        String nonceStr = Utils.UUIDGenerat("");
        Result signResult = getSignature(wxTicket.getTicket(), nonceStr, url, weChat.getAppId());
        return signResult;
    }

    public Result getTicket(String accessToken) {
        String accessTokenUrl = String
                .format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi",
                        accessToken);
        Result result = WebUtil.doGet(accessTokenUrl);
        if (result.getCode() == Constant.FAIL_)
            return result;
        try {
            WxTicket wxTicket = gson.fromJson(result.getData().toString(), WxTicket.class);
            if (wxTicket != null)
                return Result.SUCCESS(wxTicket);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return Result.FAIL();
    }

    /**
     * 微信 Signature
     */
    public Result getSignature(String ticket, String nonceStr, String url, String appId) {
        String timestamp = new Date().getTime() + "";
        String signUrl = String.format(
                "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s", ticket,
                nonceStr, timestamp, url);
        logger.info("getSignature: signUrl-> {}", signUrl);
        String sign = SHA1(signUrl);
        if (StringUtils.isEmpty(sign))
            return Result.FAIL("获取签名失败");
        WxSignature wxSignature = new WxSignature();
        wxSignature.setAppid(appId);
        wxSignature.setNonceStr(nonceStr);
        wxSignature.setTimestamp(timestamp);
        wxSignature.setSign(sign);

        logger.info("wxSignature:args :{}", gson.toJson(wxSignature));
        return Result.SUCCESS(wxSignature);
    }

    public static String wxShA1(String ticket, String noncestr, String timestamp, String url) {
        String data = String.format(
                "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s", ticket,
                noncestr, timestamp, url);
        return SHA1(data);
    }

    public static String SHA1(String decript) {
        try {
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取微信用户信息
     **/
    public Result getWxUser(String wxCode, String iv, String encData) {
      //  RuoYiConfig.WeChat weChat = humanResourcesProperty.getWechat();
        Result result = getAccessToken(wxCode);
        if (result.getCode() == Constant.FAIL_)
            return result;
        AccessToken accessToken = (AccessToken) result.getData();
        String sessionKey = accessToken.getSession_key();

        //{"phoneNumber":"13031033810","purePhoneNumber":"13031033810","countryCode":"86","watermark":{"timestamp":1748079671,"appid":"wx367440e0e545bfc6"}}
        String decrypt = AESUtil.decrypt(encData, sessionKey, iv);
        System.out.println(decrypt);
        WxPhoneInfo phoneInfo = gson.fromJson(decrypt, WxPhoneInfo.class);
        if (phoneInfo == null) {
            return Result.FAIL(DEFAULT_USER_FAIL);
        }

//        String access_token = accessToken.getAccess_token();
//        // 第三步：刷新access_token（如果需要）
//        // 此处省略
//        // 第四步：拉取用户信息(需scope为 snsapi_userinfo)
////        String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token
////                + "&openid="+openid
////                + "&lang=zh_CN";
//        String userInfoUrl = String.format(weChat.getUserinfoUrl(), access_token, openid);
//        Result userResult = WebUtil.doGet(userInfoUrl);
//        if (userResult.getCode() == Constant.FAIL_) {
//            return Result.FAIL(DEFAULT_USER_FAIL);
//        }
//        WxUser userInfo = gson.fromJson(userResult.getData().toString(), WxUser.class);
//        if (userInfo == null) {
//            return Result.FAIL(DEFAULT_USER_FAIL);
//        }
        return Result.SUCCESS(phoneInfo);
    }
}
